
import md5 from 'js-md5'

/**
 * @module 请求事件中心
 */


 /**
  * @name 事件函数项
  * @param {string} type 事件类型
  * @param {function} fn 回调函数 
  */
class EventFn{
    constructor(type,fn){
        this.type = type;
        this.fn = fn;
        this.id = this.mackId(type, fn);
    }

    mackId(type, fn){
        return md5.base64(`type:${type}, fn:${fn.toString()}`)
    }
}



class EventServe{

    constructor(){
        this._store = {};
    }


    /**
     * @name 事件注册
     * @param {stirng} type 自定义事件类型
     * @param {function} fn 回调函数
     * @param {boolean} check 事件注册检查, 单例注册
     * @return {string} id 回调id
     */
    register (type, fn, check=false){

        let fns = this._store[type] || {};
        let fnStr = fn.toString();
        
        if(this.has(type) && check){
            throw new Error(`请求事件${type}已注册`)
        }   

        if(typeof fn !== 'function'){
            throw new Error(`事件${type}绑定方法必须为函数, ${fnStr}`)
        }
        
        // 构建事件单元
        let eventItem = new EventFn(type,fn);  
        fns[eventItem.id] = eventItem;
        this._store[type] = fns;
        return eventItem.id;
        
    }


    /**
     * @name 事件触发器
     * @param {string} type 自定义事件类型
     * @param {any} data 回调参数
     * @return {array} end 回调结果 
     */ 

    trigger(type, data){

        if(this.has(type)){

            let fns = this._store[type];
            let end = [];
            
            Object.keys(fns).forEach(key =>{
                end.push(fns[key].fn(data));
            })
            
            return end;
        }
    }


    /**
     * @name 事件移除
     * @param {string} type 自定义事件类型
     * @param {string} id ? 回调id 
     */
    remove(type, id){
        let events = this._store[type];

        try{

            if(events && id){
                delete events[id];
            }else{
                delete this._store[type];
            }

        }catch(e){
            console.error(`移除事件错误: ${e}`)
        }
    }   


    /**
     * @name 事件注册检查
     * @param {string} type 自定义事件类型
     * @return {boolearn} 事件是否已注册
     */
    has(type){
        let keys = new Set(Object.keys(this._store));
        return keys.has(type);
    }
    
}


/**
 * @name 绑定全局事件服务
 * @param {string} serveName 服务名称
 * @param {boolearn} check 检查服务是否已注册
 */
EventServe.bindServe = (serveName, check=true) =>{
    const {globalData} = getApp();
    
    if(globalData[serveName] && check){
        console.error(`事件服务${serveName}已存在`)
        return
    }
    globalData[serveName] = new EventServe();

};



/**
 * 事件服务子端
 * @param {EventServe} serve ? 事件服务
 */
export class EventClient{

    constructor(serve){
        this.serve = serve || new EventServe();
        this.eventId = new Set([]);
    }

    register(type, fn){
        let id = this.serve.register(type.fn);
        this.eventId.add({id, type});
    }

    remove(type, id){
        this.serve.register(type, id);
    }

    trigger(type, data){
        this.serve.trigger(type, data);
    }  
}


export default EventServe